<?php

namespace App\Services;

use App\Models\User;
use App\Repositories\UserRepository;
use App\Exceptions\BusinessException;
use App\Services\CacheService;
use App\Services\LogService;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class WechatAuthService
{
    protected UserRepository $userRepository;
    protected CacheService $cacheService;
    protected LogService $logService;

    // 常量定义
    private const WECHAT_API_URL = 'https://api.weixin.qq.com/sns/jscode2session';
    private const SESSION_CACHE_TTL = 7200; // 2小时
    private const SESSION_CACHE_PREFIX = 'wechat_session:';
    
    // 错误码定义
    private const ERROR_CODES = [
        'AUTH_FAILED' => 40001,
        'USER_DISABLED' => 40002,
        'SESSION_EXPIRED' => 40003,
        'DECRYPT_FAILED' => 40004,
        'LOGIN_FAILED' => 50003,
    ];

    public function __construct(
        UserRepository $userRepository, 
        CacheService $cacheService, 
        LogService $logService
    ) {
        $this->userRepository = $userRepository;
        $this->cacheService = $cacheService;
        $this->logService = $logService;
    }

    /**
     * 微信小程序登录
     */
    public function login(string $code, array $userInfo = []): User
    {
        $this->validateCode($code);
        
        try {
            // 获取微信openid
            $openid = $this->getWechatOpenid($code);
            
            if (!$openid) {
                throw new BusinessException('微信授权失败', self::ERROR_CODES['AUTH_FAILED']);
            }

            // 创建或更新用户
            $user = $this->createOrUpdateUser($openid, $userInfo);

            // 缓存用户信息
            $this->cacheService->putUser($user->id, $user, CacheService::TTL_MEDIUM);

            // 记录登录活动
            $this->logUserActivity($user);

            return $user;

        } catch (BusinessException $e) {
            throw $e;
        } catch (\Exception $e) {
            $this->logError('微信登录失败', [
                'code' => $code,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            
            throw new BusinessException('登录失败，请重试', self::ERROR_CODES['LOGIN_FAILED']);
        }
    }

    /**
     * 刷新用户信息
     */
    public function refreshUserInfo(User $user, array $userInfo): User
    {
        $updateData = $this->extractUserUpdateData($userInfo);

        if (!empty($updateData)) {
            $this->userRepository->update($user->id, $updateData);
            $user->refresh();
        }

        return $user;
    }

    /**
     * 解密微信用户信息
     */
    public function decryptUserInfo(string $openid, string $encryptedData, string $iv): array
    {
        try {
            $sessionKey = $this->getSessionKey($openid);
            return $this->performDecryption($sessionKey, $iv, $encryptedData);
            
        } catch (\Exception $e) {
            $this->logError('微信用户信息解密失败', [
                'openid' => $openid,
                'error' => $e->getMessage()
            ]);
            
            throw new BusinessException('用户信息解密失败', self::ERROR_CODES['DECRYPT_FAILED']);
        }
    }

    /**
     * 验证用户状态
     */
    public function validateUser(User $user): void
    {
        if (!$user->is_active) {
            throw new BusinessException('用户已被禁用', self::ERROR_CODES['USER_DISABLED']);
        }
    }

    /**
     * 获取微信openid
     */
    private function getWechatOpenid(string $code): ?string
    {
        try {
            $response = $this->callWechatApi($code);
            $result = $response->json();
            
            if ($this->isWechatApiError($result)) {
                $this->logError('微信登录失败', [
                    'code' => $code,
                    'error' => $result['errmsg'] ?? '未知错误',
                    'errcode' => $result['errcode']
                ]);
                return null;
            }
            
            $this->cacheSessionKey($result);
            return $result['openid'] ?? null;
            
        } catch (\Exception $e) {
            $this->logError('微信API调用失败', [
                'code' => $code,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            return null;
        }
    }

    /**
     * 调用微信API
     */
    private function callWechatApi(string $code)
    {
        return Http::get(self::WECHAT_API_URL, [
            'appid' => config('easywechat.mini_app.default.app_id'),
            'secret' => config('easywechat.mini_app.default.secret'),
            'js_code' => $code,
            'grant_type' => 'authorization_code'
        ]);
    }

    /**
     * 检查微信API是否返回错误
     */
    private function isWechatApiError(array $result): bool
    {
        return isset($result['errcode']) && $result['errcode'] !== 0;
    }

    /**
     * 缓存session_key
     */
    private function cacheSessionKey(array $result): void
    {
        if (isset($result['session_key'], $result['openid'])) {
            $this->cacheService->put(
                self::SESSION_CACHE_PREFIX . $result['openid'], 
                $result['session_key'], 
                self::SESSION_CACHE_TTL
            );
        }
    }

    /**
     * 获取缓存的session_key
     */
    private function getSessionKey(string $openid): string
    {
        $sessionKey = $this->cacheService->get(self::SESSION_CACHE_PREFIX . $openid);
        
        if (!$sessionKey) {
            throw new BusinessException('Session已过期，请重新登录', self::ERROR_CODES['SESSION_EXPIRED']);
        }
        
        return $sessionKey;
    }

    /**
     * 执行解密操作
     */
    private function performDecryption(string $sessionKey, string $iv, string $encryptedData): array
    {
        // 这里需要实现实际的解密逻辑
        // 由于EasyWeChat的encryptor有问题，可能需要使用其他解密方法
        throw new \Exception('解密功能暂未实现');
    }

    /**
     * 验证code参数
     */
    private function validateCode(string $code): void
    {
        if (empty($code) || strlen($code) < 10) {
            throw new BusinessException('无效的授权码', self::ERROR_CODES['AUTH_FAILED']);
        }
    }

    /**
     * 创建或更新用户
     */
    private function createOrUpdateUser(string $openid, array $userInfo): User
    {
        $userData = [
            'openid' => $openid,
            'nickname' => $userInfo['nickName'] ?? '微信用户',
            'avatar' => $userInfo['avatarUrl'] ?? null,
            'phone' => $userInfo['phoneNumber'] ?? null,
        ];

        return $this->userRepository->createOrUpdateByOpenid($openid, $userData);
    }

    /**
     * 提取用户更新数据
     */
    private function extractUserUpdateData(array $userInfo): array
    {
        $updateData = [];
        
        $fieldMapping = [
            'nickName' => 'nickname',
            'avatarUrl' => 'avatar',
            'phoneNumber' => 'phone',
        ];
        
        foreach ($fieldMapping as $wechatField => $dbField) {
            if (isset($userInfo[$wechatField])) {
                $updateData[$dbField] = $userInfo[$wechatField];
            }
        }
        
        return $updateData;
    }

    /**
     * 记录用户活动
     */
    private function logUserActivity(User $user): void
    {
        $this->logService->logUserActivity('用户登录', $user, [
            'login_method' => 'wechat',
            'ip' => request()->ip(),
            'user_agent' => request()->userAgent(),
        ]);
    }

    /**
     * 记录错误日志
     */
    private function logError(string $message, array $context = []): void
    {
        Log::error($message, $context);
    }
}